iPhoneJS.extend({
	Hash:function(){
		var observers = [];
		var _urlAtual = document.location.href;

	    var thread = setInterval( function() { _check(); }, 400 );
		
		var _addObserver = function(obj) {
		  observers.push(obj);
		  if(_get())
		  	_notify();
		}
		
		var _check = function() {
		  if( _urlAtual != document.location.href ) {
		    _urlAtual = document.location.href;
		    _notify();
		  }
		}
		
		var _pause = function(){
			clearInterval(thread);
		}
		
		var _start = function(args){
			if(args.url) _urlAtual = args.url;
			thread = setInterval( function() { _check(); }, 400 );
		}
		
		var _notify = function() {
		  for(i=0;i<observers.length;i++) {
		    if (_urlAtual) {
		      if( observers[i] ) {
		        observers[i]( _get() );
		      } else {
		        alert("O observer numero [" + i + "] deve implementar o metodo update.");
		      }
		    }
		  }
		}
		
		var _get = function(){
			var url = location.href.toString();
			var t = url.split("#");
			if(t.length>1 && t[1].length > 0)
				return t[1];
			else
				return false;
		}
		
		return{
			addObserver:_addObserver,
			get:_get,
			pause:_pause,
			start:_start,
			urlAtual:_urlAtual
		}
	},
	History : function(){
		var _history = [];
		var _find = function(url){
			for(i=0;i<_history.length;i++){
				if(_history[i] == url)
					return [i,_history[i]];
			}
			return false;
		}
		var _go=function(url){
			if(h = _find(url)){
				while(h[0] < _history.length - 1)
					_history.pop();
				return false;
			}
			else{
				_history.push(url);
				return true;
			}
		}
		var _clear=function(){
			_history = [];
			return false;
		}
		return{
			go:_go,
			clear:_clear,
			history:_history
		}
	}
});
iPhoneJS.fn.extend({
	viewport : function(args){
		var	context = this, myhistory = new iPhoneJS.History(), hash = new iPhoneJS.Hash(), backBtn = args.backBtn || undefined, logo = args.logo || undefined;
		var content = this[0].innerHTML;
		
		bind();
		
		// bind back button
		if (backBtn)
			backBtn[0].addEventListener("click",function(e){click.apply(context,[e]);}, false)
		
		// hash controller
		hash.addObserver(function(url){load.apply(context,[{href:url}]);});
		
		function bind(){
			itens = context[0].getElementsByTagName("a");
			for(i = 0; i<itens.length;i++)
				itens[i].addEventListener("click",function(e){click.apply(context,[e]);}, false);
		}
		
		function click(e){
			e.target.className = e.target.className + " selected";
			
			if(e.target && e.target == backBtn[0])
				history.back();
			else
				load(e.target);
			
			e.preventDefault();
			return false;
		}
		
		function load(target){
			url = target.href;
			if(url) 
				next = myhistory.go(url);
			else{ //home
				next = false;
				myhistory.clear();
			}
				

			hash.pause();
			
			if(next){ //go next page
				$.ajax({
					type:"GET",
					url:url, 
					data:{}, 
					success: function(data){
						if(target.className) target.className = target.className.replace("selected","");
						slideNext.apply(context,[data, target]);
					}, 
					error:function(e){
						// TODO
						alert(e);
					}
				})
			}
			else{ //go back page
				url = hash.get();
				if(url){
					$.ajax({
						type:"GET",
						url:url, 
						data:{}, 
						success: function(data){
							if(target.className) target.className = target.className.replace("selected","");
							slideBack.apply(context,[data, target]);
						}, 
						error:function(e){
							// TODO
							alert(e);
						}
					})
				}
				else{
					if(target.className) target.className = target.className.replace("selected","");
					slideBack(content, target);					
				}
			}
		}
		
		function slideNext(content, target){
			var page, newpage, width = context[0].offsetWidth, widthWithoutPadding =  width - parseInt(context.css("padding-right")) - parseInt(context.css("padding-left"));
		
			context.attr("style","float:left;width:"+(width*2)+"px");
			context[0].innerHTML = "<div style='position:relative;float:left;width:"+widthWithoutPadding+"px'>"+context[0].innerHTML+"</div>";
			
			page = context[0].firstChild;
			newpage = page.cloneNode(true);
			newpage.innerHTML = content;
			
			newpage.style.margin = "0 0 0 "+(width-widthWithoutPadding)+"px";
			
			page.parentNode.insertBefore( newpage, page.nextSibling );
			
			barraController({next:true});

			context.translate  ({x:-width}, function(args){
				context[0].removeChild(context[0].firstChild);
				slideEnd(args, target);
			});
		}
		
		function barraController(args){
			if(args.next){
				backBtn.attr("style","");
				backBtn.css({display:"block", opacity:0});
				backBtn.transition({property:"opacity",duration:"2s"});				
				backBtn.css({opacity:1});
				//alert(backBtn.attr("style"));
			}
			else if(args.prev && args.home){
				
			}
			else{
			}
		}
		
		function slideBack(content, target){
			var page, newpage, width = context[0].offsetWidth, widthWithoutPadding =  width - parseInt(context.css("padding-right")) - parseInt(context.css("padding-left"));
		
			oldContent = context[0].innerHTML;
			
			context.attr("style","float:left;width:"+(width*2)+"px;position:relative;left:-"+width+"px");
			context[0].innerHTML = "<div style='position:relative;float:left;width:"+widthWithoutPadding+"px'>"+context[0].innerHTML+"</div>";
			
			page = context[0].firstChild;
			newpage = page.cloneNode(true);
			newpage.innerHTML = content;
			
			newpage.style.margin = "0 0 0 "+(width-widthWithoutPadding)+"px";
			
			page.parentNode.insertBefore( newpage, page.nextSibling );
			
			context.translate({x:-width,duration:"0s"};
			context.translate({x:width}, function(args){
				context[0].removeChild(context[0].lastChild);
				slideEnd(args, target);
			});
		}

		function slideEnd(args, target){
			context.attr("style","");
			context[0].innerHTML = context[0].firstChild.innerHTML;
			
			if(target.href)
				location.href = "#"+target.href;				
			
			hash.start({url:location.href});
			
			// bind links loaded
			bind();
		}
			
	}
});
